package cn.wgx.modules.sys.util;

import cn.wgx.commons.security.shiro.cache.JedisCacheManager;
import cn.wgx.commons.security.shiro.realm.CustomRealm;
import cn.wgx.commons.security.shiro.realm.CustomRealm.Principal;
import cn.wgx.commons.util.CacheUtils;
import cn.wgx.commons.util.JedisUtils;
import cn.wgx.commons.util.SpringContextHolder;
import cn.wgx.modules.sys.entity.SysPermission;
import cn.wgx.modules.sys.entity.SysUser;
import cn.wgx.modules.sys.entity.shortentity.ShortSysUser;
import cn.wgx.modules.sys.services.SysPermissionService;
import cn.wgx.modules.sys.services.SysRoleService;
import cn.wgx.modules.sys.services.SysUserService;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
 * 用户工具类
 * @author ThinkGem
 * @version 2013-12-05
 */
public class UserUtil {

	private static SysUserService sysUserService;
	private static SysRoleService sysRoleService;
	private static SysPermissionService sysPermissionService;
	private static final List<SysUser> emptyList = new ArrayList<>();



	public static final String USER_CACHE = "userCache";
	public static final String USER_CACHE_ID_ = "id_";
	public static final String USER_CACHE_LOGIN_NAME_ = "ln";
	public static final String USER_CACHE_PHONE_ = "phone_";
	public static final String USER_CACHE_EMAIL = "email_";
	public static final String USER_CACHE_LIST_BY_OFFICE_ID_ = "oid_";

	public static final String ROLES_CACHE = "roleCache";
	public static final String PERMISSION_CACHE = "perCache";
	
	public static final String CACHE_AUTH_INFO = "authInfo";
	public static final String CACHE_ROLE_LIST = "roleList";
	public static final String CACHE_MENU_LIST = "menuList";
	public static final String CACHE_AREA_LIST = "areaList";
	public static final String CACHE_OFFICE_LIST = "officeList";
	public static final String CACHE_OFFICE_ALL_LIST = "officeAllList";

	public static final String SESSION_USER = "session_user";
	

	static {
		sysUserService = SpringContextHolder.getBean("sysUserService");
		sysRoleService = SpringContextHolder.getBean("sysRoleService");
		sysPermissionService = SpringContextHolder.getBean("sysPermissionService");
	}

	/**
	 * 登出
	 */
	public static void logOut(){
		Subject subject = getSubject();
		//clearAllCache();
		if(subject != null) {
			clearCurrentUserAllCache();
			subject.logout();
		}
	}

	/**
	 * 清除当前用户缓存 Session缓存
	 */
	public static void clearCurrentUserAllCache(){
		clearCurrentSessionCache();
		clearSecondCache(getUser());
	}

	private static void clearCurrentSessionCache(){
		removeCache(SESSION_USER);
//		removeCache(CACHE_AUTH_INFO);
//		removeCache(CACHE_ROLE_LIST);
//		removeCache(CACHE_MENU_LIST);
//		removeCache(CACHE_AREA_LIST);
//		removeCache(CACHE_OFFICE_LIST);
//		removeCache(CACHE_OFFICE_ALL_LIST);
//		removeCache(ROLES_CACHE);
//		removeCache(PERMISSION_CACHE);
	}

	/**
	 * 清除指定用户缓存 二级缓存
	 * @param user
	 */
	public static void clearSecondCache(SysUser user){
		if(user == null){return;}
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getUser_id());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getUsername());
		CacheUtils.remove(USER_CACHE, USER_CACHE_EMAIL + user.getEmail());
		CacheUtils.remove(USER_CACHE, USER_CACHE_PHONE_ + user.getPhone());
	}

	public static void clearAllUserCache(){
		CacheUtils.removeAll(USER_CACHE);
	}
	/**
	 * 清除指定用户缓存 二级缓存
	 * @param userId 指定用户id
	 */
	public static void clearSecondCache(Integer userId){
		SysUser sysUser = getUserById(userId);
		clearSecondCache(sysUser);
	}

	//更新当前登陆用户的session信息，包括用户，用户权限
	public static int updateSessionUser(){
		SysUser sysUser = getUser();
		if(sysUser == null){
			return -1;
		}
		clearCurrentSessionCache();
		clearSecondCache(sysUser);
		if(sysUser.getUser_id() != null && sysUser.getUser_id() != 0){
			sysUser = getUserById(sysUser.getUser_id(),true);
		}else if(sysUser.getUsername() != null){
			sysUser = getUserByUserName(sysUser.getUsername(),true);
		}
		if(sysUser != null){
			sysUserService.getUserFilter(sysUser);
			//创建新的principal,其他权限信息会清空,重新从数据库获取
			Subject subject = SecurityUtils.getSubject();
			Principal principal = new Principal(sysUser);
			PermissionUtil.iniRoleAndPermission(principal);//初始化所有角色和权限内容,从数据库取出
			PrincipalCollection newPrincipalCollection =
					new SimplePrincipalCollection(principal, CustomRealm.realmName);
			subject.runAs(newPrincipalCollection);
//			getPrincipal().setUser(sysUser);
			//putCache(SESSION_USER, sysUser);
		}
		return 1;
	}


	public static List<ShortSysUser> getShortUser(List<SysUser> user){
		if(user == null){
			return Lists.newArrayList();
		}
		List<ShortSysUser> shortSysUsers = Lists.newArrayList();
		for(SysUser user1 : user){
			shortSysUsers.add(getShortUser(user1));
		}
		return shortSysUsers;
	}

	public static ShortSysUser getShortUser(Integer user_id){
		return getShortUser(getUserById(user_id));
	}

	public static ShortSysUser getShortUser(SysUser user){
		if(user == null){return null;}
		ShortSysUser shortSysUser = new ShortSysUser();
		BeanUtils.copyProperties(user, shortSysUser);
		return shortSysUser;
	}


	public static List<ShortSysUser> getShortUsersByIds(List<Integer> ids){
		List<SysUser> usersByIds = getUsersByIds(ids);
		List<ShortSysUser> shortSysUser = new ArrayList<>(usersByIds.size());
		for(SysUser sysUser: usersByIds){
			shortSysUser.add(getShortUser(sysUser));
		}
		return shortSysUser;
	}
	/**
	 * 获取当前用户
	 * @return
	 */
	public static SysUser getUser(){

		Subject subject = getSubject();
		if(subject == null){
			return null;
		}
		Object principal1 = subject.getPrincipal();
		if(principal1 instanceof CustomRealm.Principal){
			CustomRealm.Principal principal = (CustomRealm.Principal)principal1;
			return principal.getUser();
		}
		return null;
//		Object o = getSession().getAttribute(UserUtil.SESSION_USER);
//        if(o != null && o instanceof SysUser){
//        	return (SysUser)o;
//		}else {
//			CustomRealm.Principal principal = (CustomRealm.Principal)getSubject().getPrincipal();
//			if(principal == null) return  null;
//			SysUser user = principal.getUser();
//			getSession().setAttribute(UserUtil.SESSION_USER, user);
//			return user;
//		}
	}
	public static List<SysUser> getUsersByIds(List<Integer> ids){
		Set<Integer> s = new HashSet();
		s.addAll(ids);
		return getUsersByIds(s);
	}

	public static List<SysUser> getUsersByIds(Set<Integer> ids){
		if(ids == null || ids.isEmpty()){ return emptyList;}
		List<String> idss = new ArrayList<>();
		for(Integer id: ids){
			idss.add(USER_CACHE_ID_+id);
		}
		Jedis jedis = null;
		List<Object> list = null;
		try {
			jedis = JedisCacheManager.getResource();
			list = JedisUtils.toObjects(jedis.hmget(JedisUtils.getBytesKey("shiro_cache_" + USER_CACHE), JedisUtils.getBytessKeys(idss)));
		}catch (Exception e){}
		finally {
			JedisCacheManager.returnResource(jedis);
			//JedisUtils.returnResource(jedis);
		}
		List<SysUser> userList = new ArrayList<>();
		if(list == null)
			list = new ArrayList<>();
		for(Object o: list){
			if(o != null && o instanceof SysUser){
				userList.add((SysUser)o);
			}
		}
		if(ids.size() != userList.size()) {//补充缓存里没有找到的用户信息
			//todo
			List<Integer> noIds = checkId(ids, userList);
			List<SysUser> listByIds = sysUserService.getListByIds(noIds);
			if(listByIds!= null && !listByIds.isEmpty()){
				for(SysUser user :listByIds){
					setCache(user);
				}
				userList.addAll(listByIds);
			}
//			for (Integer id : noIds) {
//				SysUser sysUser = getUserById(id);
//				if(null != sysUser)
//					userList.add(sysUser);
//			}
		}
		sysUserService.getUserFilter(userList);
		return userList;
	}

	private static List<Integer> checkId(Set<Integer> ids, List<SysUser> sysUsers){
		List<Integer> idss = new ArrayList<>();
		for(Integer id:ids){
			boolean b = false;
			for(SysUser sysUser:sysUsers){
				b = (id.equals(sysUser.getUser_id()));
			}
			if(!b){idss.add(id);}
		}
		return idss;
	}

	//根据ID获取的用户没有MIMA
	public static SysUser getUserById(Integer id, boolean flush){
		SysUser sysUser = sysUserService.getUserByIdHasMima(id, flush);
		sysUserService.getUserFilter(sysUser);
		return sysUser;
	}

//	@RequestCache()
//	public static SysUser getUserByIdHasMima(Integer id, boolean flush){
//		SysUser sysUser = null;
//		if(flush){
//			//数据库取值
//			sysUser = sysUserService.getSysUserById(id + "", true, true );
//			if(sysUser != null){
//				setCache(sysUser);
//			}else{
//				clearSecondCache(id);
//			}
//		}else{
//			//缓存取值
//			sysUser = (SysUser) CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + id);
//			if (sysUser ==  null){
//				sysUser = sysUserService.getSysUserById(id + "", true, true );
//				if (sysUser != null){
//					setCache(sysUser);
//				}else{
//					return null;
//				}
//			}else {
//				return sysUser;
//			}
//		}
//		return sysUser;
//	}

	public static SysUser getUserById(Integer id){
		return getUserById(id, false);
	}

	public static String getUserNickNameById(Integer id){
		SysUser userById = getUserById(id, false);
		return userById == null? "" : userById.getNickname();
	}

	public static String getUserPhotoById(Integer id){
		SysUser userById = getUserById(id, false);
		return userById == null? "" : userById.getPhoto();
	}

	public static SysUser getUserByUserName(String username, boolean flush){
		SysUser sysUser;
		if(flush){
			 sysUser = sysUserService.getSysUserByUsername(username, true, false );
		}else {
			sysUser = (SysUser) CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_ + username);
			if (sysUser == null) {
				sysUser = sysUserService.getSysUserByUsername(username, true, false);
				if (sysUser == null) {
					return null;
				}

			}
		}
		if(sysUser != null)setCache(sysUser);
		return sysUser;
	}

	public static SysUser getUserByEmail(String email){
		SysUser sysUser = (SysUser) CacheUtils.get(USER_CACHE, USER_CACHE_EMAIL + email);
		if (sysUser ==  null){
			sysUser = sysUserService.getSysUserByEmail(email, true);
			if (sysUser == null){
				return null;
			}
			setCache(sysUser);
		}
		return sysUser;
	}

	public static SysUser getUserByPhone(String phone){
		SysUser sysUser = (SysUser) CacheUtils.get(USER_CACHE, USER_CACHE_PHONE_ + phone);
		if (sysUser ==  null){
			sysUser = sysUserService.getSysUserByPhone(phone, true);
			if (sysUser == null){
				return null;
			}
			setCache(sysUser);
		}
		return sysUser;
	}

	public static void setCache(SysUser sysUser){
		if(null == sysUser){return;}
		CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + sysUser.getUser_id(), sysUser);
		CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + sysUser.getUsername(), sysUser);
		if(null != sysUser.getEmail()){
			CacheUtils.put(USER_CACHE, USER_CACHE_EMAIL + sysUser.getEmail(), sysUser);
		}
		if(null != sysUser.getPhone()){
			CacheUtils.put(USER_CACHE, USER_CACHE_PHONE_ + sysUser.getPhone(), sysUser);
		}
	}

	public static List getUserMenus(Boolean tree, boolean menu){
		Subject subject = SecurityUtils.getSubject();
		try {
			subject.checkPermission("1");
		} catch (AuthorizationException e) {}
		CustomRealm.Principal principal = (CustomRealm.Principal)subject.getPrincipal();
		List<SysPermission> permissions = principal.getSysPermissions_list();
		if(permissions == null){
			PermissionUtil.iniRoleAndPermission(principal);
			principal.update();
			permissions = principal.getSysPermissions_list();
		}
		if(menu) {//是否过滤只要菜单, 字段 menu_flag 为Y的

			for(int n=permissions.size(),i=0;i<n;i++){
				SysPermission permission = permissions.get(i);
				if(!"Y".equals(permission.getMenu_flag())){
					permissions.remove(i);
					i--;
					n = permissions.size();
				}
			}
		}
		if(tree){//是否变树
			JSONArray jsonArray = sysPermissionService.sortPermission(permissions);
			return jsonArray;
		}
		return permissions;
	}


	/**
	 * 获取授权主要对象
	 */
	public static Subject getSubject(){
		return SecurityUtils.getSubject();
	}
	
	/**
	 * 获取当前登录者对象
	 */
	public static Principal getPrincipal(){
		try{
			Subject subject = getSubject();
			Principal principal = (Principal)subject.getPrincipal();
			if (principal != null){
				return principal;
			}
		}catch (UnavailableSecurityManagerException e) {
			
		}catch (InvalidSessionException e){
			
		}
		return null;
	}



	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			if (session != null){
				return session;
			}
		}catch (InvalidSessionException e){
			
		}
		return null;
	}



	//    Session Cache
	
	public static Object getCache(String key) {
		return getCache(key, null);
	}
	
	public static Object getCache(String key, Object defaultValue) {
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
		getSession().removeAttribute(key);
	}

}
